<?php

//LoadModelClass('GameRound');
include_once(Config::get('constants.MODELS_PATH') . '\GameRound.php');

class Game
{
  /** @var integer */
  public $id;
  /** @var integer */
  public $tableId;
  /** @var integer */
  public $name;
  /** @var string */
  public $status;
  /** @var boolean */
  public $hasOfficialResults;
    /** @var boolean */
  public $allowBots;
    /** @var datetime */
  public $startDate;
    /** @var datetime */
  public $endDate;
  /** @var Array<GameRound> */
  public $gameRounds = null;

  /**
   * @var Array<Game> - array of cached Game objects used when there
   *              is a need to repeatedly load the same objects from database.
   */
  private static $CACHED_GAMES = array();

  
  
  /* -------- GAME STATUSES BEGIN -------- */
  const STATUS_NEW     = 'new';
  const STATUS_STARTED = 'started';
  const STATUS_ENDED   = 'ended';

  /** @var Array<String> - dictionary of all statuses and their titles */
  public static $STATUS_TITLES = array(
    self::STATUS_NEW     => 'New',
    self::STATUS_STARTED => 'Started',
    self::STATUS_ENDED   => 'Ended'
  );


/* -------- METHODS -------- */

  /**
   * Loads a Game object from database or creates a new Game instance if no $id
   * paramenter given.
   * @param integer $id
   */
  public function __construct($id = null)
  {
    $this->Init();

    if (!$this->Load($id))
      $this->Init();
  }


  /**
   * sets default values to class's properties.
   */
  private function Init()
  {
    $this->id = -1;
    $this->tableId = -1;
    $this->status = self::STATUS_NEW;

    //bool values
    $this->hasOfficialResults = false;
    $this->allowBots   = false;
  }
  
  /**
   * Loads Game from database
   * @param integer $id - game id
   */
  private function Load($id = null)
  {
    if (!$this->LoadData($id))
      return false;

    return true;
  }
  
  /**
   * Loads a Game from database
   * @param integer $id - game id
   * @return boolean true if object was loaded
   */
  protected function LoadData($id = null)
  {
    if (!is_numeric($id))
      return false;
    else
    {
      $games = DB::table('games')->where('id', '=', $id)->first();
      if (count($games) == 0)
        return false;
    }
    $this->SetPropertyValues($games);

    return true;
  }

  /**
   * Populates basic Game properties from with data extracted from database.
   * @param array $data - dictionary of (<table column name> => <value>)
   */
  protected function SetPropertyValues(&$data)
  {
    $this->id          = $data->id;
    $this->tableId     = $data->table_id;
    $this->name        = $data->name;
    $this->status      = $data->status;
    $this->startDate   = $data->start_date;
    $this->endDate     = $data->end_date;
    $this->roundNumber = $data->round_number;

    //bool values
    $this->hasOfficialResults = (boolean) $data->has_official_results;
    $this->allowBots   = (boolean) $data->allow_bots;
  }
  
  /**
   * Saves or adds a new Game to DB
   */  
  public function Save()
  {
    $values = array();
    
    $values['table_id']     = intval($this->tableId);
    $values['name']         = $this->name;
    $values['status']       = $this->status;
    $values['start_date']   = $this->startDate;
    $values['end_date']     = $this->endDate;
    $values['round_number'] = $this->roundNumber;
    
    // bool values
    $values['has_official_results'] = (boolean) $this->hasOfficialResults;
    $values['allow_bots']   = (boolean) $this->allowBots;

    $oldGame = new Game($this->id);
    if ($oldGame->id && $oldGame->id > 0)
    {
      $res = DB::table('games')
              ->where('id', '=', $oldGame->id)
              ->update($values);
    }
    else
      $res = DB::table('games')->insert($values);
  }

  /**
   * Saves $this->roundNumber to database.
   */
  public function SaveRoundNumber()
  {
    if (!is_numeric($this->id))
      return;
    
    $values = array();
    $values['round_number'] = $this->roundNumber;
    DB::table('games')->where('id', '=', $this>id)->update($values);
  }

  /**
   * Loads given game perdiod.
   * @param Integer $roundNumber
   * @return GameRound
   */
  public function GetGameRound($roundNumber)
  {
    if ($this->gameRounds === null)
      $this->LoadGameRounds();
    
    $gameRound = $this->gameRounds[$roundNumber];
    return is_numeric($gameRound->id) ? $gameRound : new GameRound();
  }
  
  /**
   * Returns all game's rounds
   * @return Array<GameRound>
   */
  public function GetGameRounds()
  {
    if ($this->gameRounds === null)
      $this->LoadGameRounds();
    
    return $this->gameRounds;
  }
  
  /**
   * Loads game's rounds from database.
   * @return type
   */
  private function LoadGameRounds()
  {
    $this->gameRounds = array();
    
    $gameRounds = GameRound::LoadGameRounds($this->id);
    foreach ($gameRounds as $gameRound)
      $this->gameRounds[$gameRound->roundNumber] = $gameRound;
  }

  /**
   * Deletes a Game object from database.
   * @return boolean
   */
  public function Delete()
  {
    if (!is_numeric($this->id))
      return false;

    $gameId = $this->id;
    // set successful return
    $res = DeleteRow('games', "id=" . ToSqlQuotedString($gameId));
    $res = DB::table('games')->where('id', '=', $this>id)->delete();
    $res = DB::table('game_players')->where('game_id', '=', $this>id)->delete();
    $res = DB::table('game_rounds')->where('game_id', '=', $this>id)->delete();
    
    return $res;
  }

  /**
   * Starts a game
   * @return boolean
   */
  public function StartGame()
  {
    if ($this->status != Game::STATUS_NEW)
      return false;
    $this->status = Game::STATUS_STARTED;
    // double check that the start date and end date is set
    $this->startDate = date('Y-m-d', time());
    $this->Save();
    
    if ($this->IsDietBet10Game())
    {
      $gameRound = $this->GetGameRound(1);
      $this->MarkRoundAsStarted($gameRound);
    }
  }
    
}
?>
